#ifndef CLIB_CLIB_CONTAINER_DOUBLE_ENDED_VECTOR_H
#define CLIB_CLIB_CONTAINER_DOUBLE_ENDED_VECTOR_H

#include "../../base/clib_base.h"

CLIB_CPLUS_SUPPORT_START

/**
 * 一个双端动态数组
 * 支持两端常数时间插入和移除以及常数时间访问
 */
struct clib_container_double_ended_vector;


struct clib_container_double_ended_vector_conf {
    /**
     * 队列容量
     */
    size_t init_capacity;

    /**
    * 内存分配函数
    * @param size 需要分配的大小
    * @return
    */
    void *(*mem_malloc_func)(size_t size);

    /**
     * 内存释放函数
     * @param block 块指针
     */
    void (*mem_free_func)(void *block);

    /**
     * 内存拷贝函数
     * @param target 目标
     * @param src 源
     * @param size 大小
     * @return
     */
    void *(*mem_copy_func)(void *target,const void *src, size_t size);
};

/**
 * 创建一个双端动态数组
 * @param conf
 * @param vector
 * @return
 */
int clib_container_double_ended_vector_create_with_conf(
        const struct clib_container_double_ended_vector_conf *const conf,
        struct clib_container_double_ended_vector **vector);

/**
 * 销毁一个双端动态数组
 * @param vector 双端动态数组对象
 */
void clib_container_double_ended_vector_destroy(
        struct clib_container_double_ended_vector *vector);

/**
 * 在最后添加数据
 * @param vector 双端动态数组对象
 * @param element 要添加的元素
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_ended_vector_add(
        struct clib_container_double_ended_vector *vector,
        void *element);

/**
 * 在最后添加数据
 * @param vector 双端动态数组对象
 * @param element 要添加的元素
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_ended_vector_add_last(
        struct clib_container_double_ended_vector *vector,
        void *element);

/**
 * 在最开始添加数据
 * @param vector 双端动态数组对象
 * @param element 要添加的元素
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_ended_vector_add_first(
        struct clib_container_double_ended_vector *vector,
        void *element);


/**
 * 在指定索引处添加数据
 * @param vector 双端动态数组对象
 * @param element 要添加的元素
 * @param index 要添加的元素索引
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_ended_vector_add_with_index(
        struct clib_container_double_ended_vector *vector,
        void *element,
        size_t index);

/**
 * 在指定索引处替换数据
 * @param vector 双端动态数组对象
 * @param element 要替换的元素
 * @param index 要替换的元素索引
 * @param out 替换之前的数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int
clib_container_double_ended_vector_replace_with_index(
        struct clib_container_double_ended_vector *vector,
        void *element,
        size_t index,
        void **out);

/**
 * 查询指定元素在数组中的索引
 * @param vector 双端动态数组对象
 * @param element 要查询的元素
 * @param index 查询出的索引指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_ended_vector_index_of(
        struct clib_container_double_ended_vector const *vector,
        const void *element,
        size_t *index);


/**
 * 删除第一个数据
 * @param vector  双端动态数组对象
 * @param out 删除前存储得到数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_ended_vector_remove_first(
        struct clib_container_double_ended_vector *vector,
        void **out);

/**
 * 删除最后一个数据
 * @param vector 双端动态数组对象
 * @param out 删除前存储得到数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_ended_vector_remove_last(
        struct clib_container_double_ended_vector *vector,
        void **out);


/**
 * 删除指定索引的数据
 * @param vector 双端动态数组对象
 * @param index 要删除的数据索引
 * @param out 删除之前的数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int
clib_container_double_ended_vector_remove_with_index(
        struct clib_container_double_ended_vector *vector,
        size_t index,
        void **out);

/**
 * 删除指定元素
 * @param vector 双端动态数组对象
 * @param element 删除的元素
 * @param out 删除之前的数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_ended_vector_remove(
        struct clib_container_double_ended_vector *vector,
        void *element,
        void **out);


/**
 * 获取指定索引的数据
 * @param vector 双端动态数组对象
 * @param index 查询的索引
 * @param out 获取到的数据
 * @return
 * 成功 0
 * 失败 非0
 */
int
clib_container_double_ended_vector_get_with_index(
        struct clib_container_double_ended_vector const *vector,
        size_t index,
        void **out);

/**
 * 获取第一个元素
 * @param vector 双端动态数组对象
 * @param out 获取到的数据
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_ended_vector_get_first(
        struct clib_container_double_ended_vector const *vector,
        void **out);


/**
 * 获取最后一个元素
 * @param vector 双端动态数组对象
 * @param out 获取到的数据
 * @return
 * 成功 0
 * 失败 非0
 */
int
clib_container_double_ended_vector_get_last(
        struct clib_container_double_ended_vector const *vector,
        void **out);


/**
 * 将双端可变数组对象的容量进行修剪
 * 变为可以满足要求的最小容量
 * @param vector 双端动态数组对象
 * @return
 */
int clib_container_double_ended_vector_trim_capacity(
        struct clib_container_double_ended_vector *vector);


/**
 * 翻转数据
 * @param vector 双端动态数组对象
 */
void clib_container_double_ended_vector_reverse(
        struct clib_container_double_ended_vector *vector);

/**
 * 查询是否包含元素
 * @param vector  双端动态数组对象
 * @param element 查询的元素
 * @return 包含的指定元素个数
 */
size_t clib_container_double_ended_vector_contains(
        struct clib_container_double_ended_vector const *vector,
        const void *element);

/**
 * 获取当前数组存储元素个数
 * @param vector 双端动态数组对象
 * @return 元素个数
 */
size_t
clib_container_double_ended_vector_get_current_size(
        struct clib_container_double_ended_vector const *vector);


/**
 * 获取当前容量
 * @param vector 双端动态数组对象
 * @return 当前容量
 */
size_t clib_container_double_ended_vector_get_capacity(
        struct clib_container_double_ended_vector const *vector);


CLIB_CPLUS_SUPPORT_END

#endif //CLIB_CLIB_CONTAINER_DOUBLE_ENDED_VECTOR_H
